//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V1.0.1
#include "ws2812b_driver.h"
#include <string.h>

typedef union
{
    uint32_t GRB888_Value;
    struct
    {
        uint8_t B;  // B值
        uint8_t R;  // R值
        uint8_t G;  // G值
    }Color;
}WHT_WS2812B_GRB888_t;

static uint8_t WHT_WS2812B_GRB_Bit_Buffer[WS2812B_MAX_Lights_Count+1][WS2812B_RGB_Bit];

static uint8_t WHT_WS2812B_0_Code_Time_Count;
static uint8_t WHT_WS2812B_1_Code_Time_Count;

static SemaphoreHandle_t Tx_xSemaphore;//二值信号量句柄

static void IT_Callback(void)
{
    BaseType_t xHigherPriorityTaskWoken;

    xSemaphoreGiveFromISR(Tx_xSemaphore, &xHigherPriorityTaskWoken);//释放信号量
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

static const WHT_Timer_PWM_Out_Config_t PWM_Out_Config[1] =
{
    {
        .Channel = Timer_CH3,
        .Idle_IT_Callback = IT_Callback,
        .Normal_Polarity = Hig,
        .Normal_Idle_Polarity = Low,
        .Normal_Output_GPIO_Port = PortA,
        .Normal_Output_GPIO_Pin = Pin2,
        .Complementary_Output_State = DISABLE,
        .Brake_Output_State = DISABLE,
    },
};
static WHT_Timer_Config_t PWM_Config =
{
    .Name     = Timer2,
    .Cycle_ns = WS2812B_Cycle_ns,
    .Mode     = Timer_Output_Comparison,
    .Config_Count = sizeof(PWM_Out_Config) / sizeof(PWM_Out_Config[0]),
    .Config   = &PWM_Out_Config,
};
static void WHT_WS2812B_Driver_Init(void)
{
    WHT_Timer_BSP.WHT_Config(&PWM_Config);
    WHT_Timer_BSP.WHT_Start(&PWM_Config);
    WHT_WS2812B_0_Code_Time_Count = (uint8_t)((float)PWM_Config.Auto_Reload * WS2812B_0_Code_ns / WS2812B_Cycle_ns + 0.5f);
    WHT_WS2812B_1_Code_Time_Count = (uint8_t)((float)PWM_Config.Auto_Reload * WS2812B_1_Code_ns / WS2812B_Cycle_ns + 0.5f);
}



static void WHT_WS2812B_Set_LRGB(uint16_t number, WHT_LRGB_t* lrgb8888)
{
    WHT_WS2812B_GRB888_t WHT_WS2812B_GRB888;
    uint8_t* Buffer_Value;

    if (number > WS2812B_MAX_Lights_Count)
        return;

    Buffer_Value = WHT_WS2812B_GRB_Bit_Buffer[number];
    
    WHT_WS2812B_GRB888.Color.R = (lrgb8888->R * lrgb8888->L + 127) >> 8; // 四舍五入
    WHT_WS2812B_GRB888.Color.G = (lrgb8888->G * lrgb8888->L + 127) >> 8; // 四舍五入
    WHT_WS2812B_GRB888.Color.B = (lrgb8888->B * lrgb8888->L + 127) >> 8; // 四舍五入

    for (int i = 0; i < WS2812B_RGB_Bit; i++)
    {
        // G R B（MSB）
        Buffer_Value[i] = (WHT_WS2812B_GRB888.GRB888_Value & (1 << (WS2812B_RGB_Bit - 1 - i))) ? WHT_WS2812B_1_Code_Time_Count : WHT_WS2812B_0_Code_Time_Count;
    }
}

static void WHT_WS2812B_Set_All_LRGB(WHT_LRGB_t* lrgb8888)
{
    WHT_WS2812B_Set_LRGB(0, lrgb8888);
    for (int i = 1; i < WS2812B_MAX_Lights_Count; i++)
    {
        *((uint32_t*)WHT_WS2812B_GRB_Bit_Buffer[i] + 0) = *((uint32_t*)WHT_WS2812B_GRB_Bit_Buffer[0] + 0);
        *((uint32_t*)WHT_WS2812B_GRB_Bit_Buffer[i] + 1) = *((uint32_t*)WHT_WS2812B_GRB_Bit_Buffer[0] + 1);
        *((uint32_t*)WHT_WS2812B_GRB_Bit_Buffer[i] + 2) = *((uint32_t*)WHT_WS2812B_GRB_Bit_Buffer[0] + 2);
        *((uint32_t*)WHT_WS2812B_GRB_Bit_Buffer[i] + 3) = *((uint32_t*)WHT_WS2812B_GRB_Bit_Buffer[0] + 3);
        *((uint32_t*)WHT_WS2812B_GRB_Bit_Buffer[i] + 4) = *((uint32_t*)WHT_WS2812B_GRB_Bit_Buffer[0] + 4);
        *((uint32_t*)WHT_WS2812B_GRB_Bit_Buffer[i] + 5) = *((uint32_t*)WHT_WS2812B_GRB_Bit_Buffer[0] + 5);
    }
}

static void WHT_WS2812B_Start(void)
{
    WHT_Timer_BSP.WHT_Set_Duty_Cycle_DMA(&PWM_Config, PWM_Out_Config->Channel, WHT_WS2812B_GRB_Bit_Buffer[0], sizeof(WHT_WS2812B_GRB_Bit_Buffer));
    xSemaphoreTake(Tx_xSemaphore, portMAX_DELAY);//等待信号量
    WHT_Timer_BSP.WHT_Stop(&PWM_Config);
    vTaskDelay(1);
}

static void WHT_WS2812B_Init(void)
{
    Tx_xSemaphore = xSemaphoreCreateBinary();
    WHT_WS2812B_Driver_Init();
}

const WHT_WS2812B_Driver_t WHT_WS2812B_Driver =
{
    .WHT_Init         = WHT_WS2812B_Init,
    .WHT_Start        = WHT_WS2812B_Start,
    .WHT_Set_LRGB     = WHT_WS2812B_Set_LRGB,
    .WHT_Set_All_LRGB = WHT_WS2812B_Set_All_LRGB,
};
